/*========================================================/
;
;  FILE:     MOUSE.C
;  DATE:     AUG 06, 96
;
;  COMMENTS: A few simple mouse  and joystick functions.
;            (for changes look for a search pattern /@.../)
;
;  HISTORY:
;
;  Kelly & SMR [Aug 6, 96]/@MRS/:
;            CRAZY mouse behaviour is now detected and
;            mouse is being reset.
;
/========================================================*/

#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>
#include <bios.h>

#include <time.h> //SMR

#include "rad.h"

#include "mouse.h"
#include "player.h"
#include "debug.h"

extern void clearInterupts(void);
#pragma aux clearInterupts = "cli";
extern void setInterupts(void);
#pragma aux setInterupts = "sti";

#define TRUE 1
#define FALSE 0
#define SOHIGHITMUSTBEUNPLUGGED 1500

//void mouseStatus(mousestateptr m); //[SMR]
time_t mouseStatus(mousestateptr m);

int initmouse();
void hidemouse();
char g_mousetype = MT_UNK;;

extern long g_userbuttons;
extern long g_deltax;
extern long g_deltay;

int centerX;
int centerY;
int oldX;
int oldY;
int curDebugJoyX;
int curDebugJoyY;
	
extern JOYDATA g_joydata;
void getJoyPos(void);

/***************************************************************************\
* getJoyPos - get the x and y coords of joystick
\***************************************************************************/

void getJoyPos(void)
{
	clearInterupts();

	g_joydata.tempx=0;
	g_joydata.tempy=0;
	g_joydata.buttons=0;

	outp(0x201, 0xFF);
	do
	{
		g_joydata.buttons = inp(0x201);
		g_joydata.tempx += g_joydata.buttons & 1;
		g_joydata.tempy += g_joydata.buttons & 2;
		if (g_joydata.tempx > SOHIGHITMUSTBEUNPLUGGED)
		{
			fatalerror("You must have a joystick plugged in or run setup again");
		}
	}
	while ((g_joydata.buttons&3) != 0);

	setInterupts();
	g_joydata.tempy /= 2;
	
	if (g_joydata.tempx > xJoyMax)
		xJoyMax = g_joydata.tempx;
	if (g_joydata.tempy > yJoyMax)
	{
		yJoyMax = g_joydata.tempy;
		g_joydata.centery = (yJoyMax /2);
	}
	if (g_joydata.tempx < xJoyMin) xJoyMin = g_joydata.tempx;
	if (g_joydata.tempy < yJoyMin) yJoyMin = g_joydata.tempy;

	g_joydata.tempx = (g_joydata.tempx* 320 / xJoyMax);
	g_joydata.tempy = (g_joydata.tempy* 160 / yJoyMax);

	g_deltax = -(g_player.x - g_joydata.tempx);
	g_deltay = (g_player.y - g_joydata.tempy);

	switch ((g_joydata.buttons/16)&3)
	{
		case 0:
			//both buttons down
			g_userbuttons=3; 
			break;
		case 1:
			g_userbuttons=2; 
			break;
		case 2:
			g_userbuttons=1; 
			break;
		case 3:
			g_userbuttons=0; 
			break;
	}
}

/*
 * initmouse()
 *
 * Initializes the mouse handler at BIOS interrupt 33h.
 * Returns TRUE if successful, FALSE if not.
 */

int initmouse()
{
	union REGS reg;
	
	reg.w.ax=M_RESET;
	int386(MOUSEBIOS,&reg,&reg);


	if(reg.w.ax)
	{
	    reg.w.ax=M_GETTYPE;
	    int386(MOUSEBIOS,&reg,&reg);

	      if((reg.w.cx & MT_PS2) == MT_PS2) g_mousetype = MT_PS2;
	      else g_mousetype = MT_UNK;
	    return(TRUE);
	}
	else
	    return(FALSE);
}


/*
 * hidemouse
 */
void hidemouse()
{
	union REGS reg;
	reg.w.ax=M_HIDE;
	int386(MOUSEBIOS,&reg,&reg);
}

/*
 * MouseStatus()
 *
 * Fills up a structure with the mouse button and position info.
 */
time_t mouseStatus(mousestateptr m)
{
	union REGS reg;

	static int counter=0;
	static int CRAZY = 0;

        //static int     start_cl,end_cl,delay_cl;
        //static clock_t delay_time=0;  //unsigned long
	//static clock_t start_time=0,end_time=0;

	reg.w.ax=M_STATUS;
	int386(MOUSEBIOS,&reg,&reg);
	m->button=reg.w.bx;
	m->x=reg.w.cx;
	m->y=reg.w.dx;

        /* An attempt to catch a moment when mouse goes CRAZY [SMR]
        // end_cl = start_cl;
        // reg.w.ax = 0;
        // int386(TIMERBIOS,&reg,&reg);
        // start_cl = reg.w.dx;
        // delay_cl = start_cl - end_cl;


        // end_time   = start_time;
        // start_time = clock();
        // delay_time = start_time - end_time;
	*/

	reg.w.ax=M_DELTA;
	int386(MOUSEBIOS,&reg,&reg);
	m->dh=reg.w.cx;
	m->dv=reg.w.dx;

        // This catches CRAZY mouse and resets it /@MRS/
        if (ABS(m->dh)>1500 || ABS(m->dv)>1500) counter+=5;
	else counter--;
	if (counter<-10) counter=0;
        if (counter>75)  CRAZY=1;

        if (CRAZY && (g_mousetype == MT_PS2)) {
	  reg.w.ax=M_RESET;
	  int386(MOUSEBIOS,&reg,&reg);
	  CRAZY=0;
	}

return  0;//delay_time;
}

/*
 * MoveMouse
 *
 * Sets the position of the mouse
 */

void moveMouse(short x,short y)
{
	union REGS reg;
	
	reg.w.ax=M_MOVE;
	reg.w.cx=x;
	reg.w.dx=y;
	int386(MOUSEBIOS,&reg,&reg);
}

/*
 * ConstrainMouse
 *
 * Constrains the mouse to a rectangle
 *
 */

void constrainmouse(short left,short top,short right,short bottom)
{
	union REGS reg;

	reg.w.ax=M_HRANGE;
	reg.w.cx=left;
	reg.w.dx=right;
	int386(MOUSEBIOS,&reg,&reg);
	reg.w.ax=M_VRANGE;
	reg.w.cx=top;
	reg.w.dx=bottom;
	int386(MOUSEBIOS,&reg,&reg);
}

